package net.hands.ado.db.jdbc;

import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;

import net.hands.ado.db.DBException;
import net.hands.ado.db.DBTable;
import net.hands.common.Convert;
import net.hands.common.StringUtils;
import net.hands.common.coll.ParameterMap;

public class DatabaseMeta {
	public final static String MySQL = "mysql";

	public final static String Oracle = "oracle";

	public final static String HSQL = "hsql";

	public final static String MSSQL_SERVER = "sqlserver";

	public final static String POSTGRESQL = "postgresql";

	// private DatabaseMetaData meta;
	/**
	 * 来至数据库表实体
	 */
	private final Map<String, DBTable> tables = new HashMap<String, DBTable>();

	public DatabaseMeta(final DatabaseMetaData meta, final boolean isSynonyms) {
		// TODO Auto-generated constructor stub
		// this.meta = meta;
		String catalog = null, schema = null, name = null;
		String[] types;
		if (Convert.toBool(isSynonyms, false)) {
			types = new String[] { "TABLE", "VIEW", "SYNONYM" };
		} else {
			types = new String[] { "TABLE", "VIEW" };
		}
		try {
			ResultSet rs = null;
			try {
				if (meta.storesMixedCaseQuotedIdentifiers()) {
					rs = meta.getTables(catalog, schema, name, types);
				} else if (meta.storesUpperCaseQuotedIdentifiers()
						|| meta.storesUpperCaseIdentifiers()) {
					rs = meta.getTables(StringUtils.toUpperCase(catalog),
							StringUtils.toUpperCase(schema),
							StringUtils.toUpperCase(name), types);
				}
				DBTable table = null;
				while (rs.next()) {
					String tableName = rs.getString("TABLE_NAME");
					table = new DBTable(tableName, meta);
					tables.put(tableName, table);
				}

			} finally {
				rs.close();
			}
		} catch (SQLException sqlException) {
			throw DBException.of("could not get table metadata: " + name);
		}

	}

	/**
	 * 数据库中表
	 * 
	 * @param name
	 * @return
	 */
	public DBTable getDBTable(final String name) {
		DBTable table = (DBTable) tables.get(name);
		if (table != null) {
			return table;
		} else {
			throw DBException.of("could not get table metadata: " + name);
		}

	}

	String _url;

	String _databaseProductName;

	private final ParameterMap _alias = new ParameterMap()
			.add("Oracle", Oracle).add("Microsoft SQL Server", MSSQL_SERVER)
			.add("MySQL", MySQL).add("HSQL Database Engine", HSQL)
			.add("PostgreSQL", POSTGRESQL);

	public String getDatabaseProductName() {
		return StringUtils.blank(_alias.get(_databaseProductName));
	}

	public String getUrl() {
		return _url;
	}

	public boolean isOracle() {
		return Oracle.equals(getDatabaseProductName());
	}

	public boolean isMySql() {
		return MySQL.equals(getDatabaseProductName());
	}

	public boolean isHSql() {
		return HSQL.equals(getDatabaseProductName());
	}

	public boolean isMSSql() {
		return MSSQL_SERVER.equals(getDatabaseProductName());
	}

	public boolean isPostgreSql() {
		return POSTGRESQL.equals(getDatabaseProductName());
	}
}
